package twoD.IsoPfem;

import inf.jlinalg.Vector2D;

public abstract class Edge implements IEdge {

	private Node[] n_ = new Node[2];
	private int[][] dofNumbers_;
	private Constraint constraint_;
	private int nModes_;
	private Force[] nodalF_;
	private Vector2D[] displacement_;

	public Edge(Node n1, Node n2) {
		n_[0] = n1;
		n_[1] = n2;
		setMode(1);
	}

	@Override
	public void setConstraint(Constraint c) {
		constraint_ = c;
	}

	@Override
	public Node getN1() {
		return n_[0];
	}

	@Override
	public Node getN2() {
		return n_[1];
	}

	@Override
	public Node getNode(int i) {
		return n_[i];
	}

	@Override
	public void setMode(int n) {
		nModes_ = n;
		displacement_ = new Vector2D[n];
	}

	@Override
	public int getNumberOfModes() {
		return nModes_;
	}

	@Override
	public int enumerateDOFs(int d, int start) {
		dofNumbers_ = new int[2][];
		// collect enumeration of nodes
		dofNumbers_[0] = new int[getN1().getDofNumbers().length
				+ getN2().getDofNumbers().length];
		int cnt = 0;
		for (int i : getN1().getDofNumbers())
			dofNumbers_[0][cnt++] = i;
		for (int i : getN2().getDofNumbers())
			dofNumbers_[0][cnt++] = i;

		// enumerate dof for modes on edge
		dofNumbers_[1] = new int[d * getNumberOfModes()];
		for (int i = 0; i < getNumberOfModes(); i++) {
			if (constraint_ != null)
				for (int j = 0; j < d; j++)
					if (constraint_.isFree(j))
						dofNumbers_[1][d * i + j] = start++;
					else
						dofNumbers_[1][d * i + j] = -1;
			else
				for (int j = 0; j < d; j++)
					dofNumbers_[1][d * i + j] = start++;

		}
		return start;
	}

	@Override
	public int[] getDofNumbers() {
		return dofNumbers_[1];
	}

	@Override
	public void addNodalForce(double[]... f) {
		if (nodalF_ != null)
			for (int i = 0; i < nModes_; i++)
				nodalF_[i].add(f[i]);
		else {
			nodalF_ = new Force[nModes_];
			for (int i = 0; i < nModes_; i++)
				nodalF_[i] = new Force(f[i]);
		}
	}

	@Override
	public Force[] getNodalForceVector() {
		return nodalF_;
	}

	@Override
	public Node getCommonNode(IEdge e) {
		Node n0 = e.getN1();
		if (n0 == n_[0] || n0 == n_[1])
			return n0;
		else {
			Node n1 = e.getN2();
			if (n1 == n_[0] || n1 == n_[1])
				return n1;
			else
				return null;
		}
	}

	@Override
	public void setDisplacement(double[] u) {
		for (int i = 0; i < getNumberOfModes(); i++)
			displacement_[i] = new Vector2D(u[i * 2], u[i * 2 + 1]);
	}

	@Override
	public Vector2D getDisplacement(int i) {
		return displacement_[i];
	}

	@Override
	public boolean contain(Node n) {
		return (getN1() == n) || (getN2() == n);
	}

	@Override
	public boolean contain(Node... N) {
		boolean tmp = true;
		for (Node n : N)
			tmp = tmp && contain(n);
		return tmp;
	}
}
